package com.tanhua.server;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.Constants;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.enums.CommentType;
import com.tanhua.exception.BusinessException;
import com.tanhua.interceptor.UserHolder;
import com.tanhua.model.UserInfo;
import com.tanhua.mondb.Comment;
import com.tanhua.mondb.Movement;
import com.tanhua.vo.ErrorResult;
import com.tanhua.vo.MovementsVo;
import com.tanhua.vo.PageResult;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementsService {

    @DubboReference
    private MovementApi movementApi;
    @Autowired
    private OssTemplate ossTemplate;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private CommentApi commentApi;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
   /*
        发布个人动态
   * */
    public void publishMovements(Movement movement, MultipartFile[] imageContent) throws BusinessException, IOException {
        //判断发布内容是否为空
        if(StringUtils.isEmpty(movement.getTextContent())){
                throw  new BusinessException(ErrorResult.contentError());
        }
        //获取当前用户的id
        Long userId = UserHolder.getUserId();
        //将图片上传致阿里云
        ArrayList<String> Medias = new ArrayList<>();
        for(MultipartFile multipartFile :imageContent){
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            Medias.add(upload);
        }
        //封装成一个圈子对象
        movement.setUserId(userId);
        movement.setMedias(Medias);
        //保存圈子里面
        movementApi.publish(movement);
    }
    /*
    * 查看我的动态
    * */
    public PageResult movementsByUserId(Long userId, Integer page, Integer pageSize) {
        //根据userid将我的发布的动态进行分页查询，封装成结果页，结果页中的items集合保存一个一个的Movement对象
       PageResult pr = movementApi.movementsByUserId(userId,page,pageSize);

        List<Movement> items = (List<Movement>) pr.getItems();

        if(items==null){
            return  pr;
        }
        UserInfo userInfo = userInfoApi.findById(userId);

        ArrayList<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items){
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vos.add(vo);
        }
        pr.setItems(vos);
        return pr;
    }
    /*
    * 查询好友动态
    * */
    public PageResult findFriendMovements(Integer page, Integer pageSize) {
        //获取用户的id
        Long userId = UserHolder.getUserId();
        //获取用户好友的动态
        List<Movement> items =movementApi.findFriendMovements(page,pageSize,userId);
        //判断用户的动态的是否为空
        if(CollUtil.isEmpty(items)){
            //为空返回默认的状态
            return  new PageResult();
        }
        //提取动态发布人的id列表
        List<Long> userIds =  CollUtil.getFieldValues(items,"userId",Long.class);
        //根据用户的的id列表获取用户的详情
        Map<Long, UserInfo> map= userInfoApi.findByIds(userIds, null);
        //不为空封装movementvo对象
        ArrayList<MovementsVo> vos = new ArrayList<>();
        for(Movement movement : items){
            UserInfo userInfo = map.get(movement.getUserId());
            if(userInfo!=null){
                MovementsVo vo = MovementsVo.init(userInfo,movement);
                String key = Constants.MOVEMENTS_INTERACT_KEY + movement.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                if(redisTemplate.opsForHash().hasKey(key,hashKey)){
                    vo.setHasLiked(1);
                }
                vos.add(vo);
            }
        }
        return new PageResult(page,pageSize,0L,vos);

    }

    /*
    * 查询推荐动态
    * */
    public PageResult findRecommendMovements(Integer page, Integer pageSize) {
        //获取用户id
        String redisKey = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUserId();
        String redisData = this.redisTemplate.opsForValue().get(redisKey);
        List<Movement> list = Collections.EMPTY_LIST;
        //对redis进行是否为空进行判断
        if(StringUtils.isEmpty(redisData)){
            //为空调用mongodbApi进行随机分配
            list = movementApi.randomMovements(pageSize);
        }else {
            //不为空使用redis进行分配数据
            String[] split = redisData.split(",");
            if ((page-1) * pageSize > split.length) {
                return new PageResult();
            }
            List<Long> pids = Arrays.stream(split)
                    .skip((page - 1) * pageSize)
                    .limit(pageSize)
                    .map(e ->Long.valueOf(e))
                    .collect(Collectors.toList());
            list = movementApi.findMovementByIds(pids);
        }
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //5、循环数据列表
        Map<Long, UserInfo> userMaps = userInfoApi.findByIds(userIds, null);
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : list) {
            //5、一个Movement构建一个Vo对象
            UserInfo userInfo = userMaps.get(item.getUserId());
            if(userInfo!=null){
                MovementsVo vo = MovementsVo.init(userInfo, item);
                String key = Constants.MOVEMENTS_INTERACT_KEY + item.getId().toHexString();
                String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
                if(redisTemplate.opsForHash().hasKey(key,hashKey)){
                    vo.setHasLiked(1);
                }
                vos.add(vo);
            }


        }
        //6、构建返回值
        return new PageResult(page,pageSize,0L,vos);
    }
    /*
     * 查看单个动态
     * */
    public MovementsVo findMovementById(String movementId) {
        Movement movements = movementApi.findById(movementId);
        if(movements == null) {
            return null;
        }else {
            UserInfo userInfo = userInfoApi.findById(movements.getUserId());
            return MovementsVo.init(userInfo,movements);
        }
    }
    /*
     * 查询点赞数
     * */
    public Integer likeComment(String movementId) throws BusinessException {
        //1、调用API查询用户是否已点赞
        Boolean hasComment = commentApi.hasComment(movementId,UserHolder.getUserId(), CommentType.LIKE);
        //2、如果已经点赞，抛出异常
        if(hasComment) {
            throw new BusinessException(ErrorResult.likeError());
        }
        //3、调用API保存数据到Mongodb
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.save(comment);
        //4、拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return count;
    }
    /*
    * 取消点赞
    * */
    public Integer dislikeComment(String movementId) throws BusinessException {
        //1、调用API查询用户是否已点赞
        Boolean hasComment = commentApi.hasComment(movementId,UserHolder.getUserId(),CommentType.LIKE);
        //2、如果未点赞，抛出异常
        if(!hasComment) {
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //3、调用API，删除数据，返回点赞数量
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setUserId(UserHolder.getUserId());
        Integer count = commentApi.delete(comment);
        //4、拼接redis的key，删除点赞状态
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }
    /*
    喜欢
    */
    public Integer loveComment(String movementId) throws BusinessException {
        //1、调用API查询用户是否已点赞
        Boolean hasComment = commentApi.hasComment(movementId,UserHolder.getUserId(),CommentType.LOVE);
        //2、如果已经喜欢，抛出异常
        if(hasComment) {
            throw  new BusinessException(ErrorResult.loveError());
        }
        //3、调用API保存数据到Mongodb
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.save(comment);
        //4、拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return count;
    }

    /*
    * 取消喜欢
    * */
    public Integer disloveComment(String movementId) throws BusinessException {
        //1、调用API查询用户是否已点赞
        Boolean hasComment = commentApi.hasComment(movementId,UserHolder.getUserId(),CommentType.LOVE);
        //2、如果未点赞，抛出异常
        if(!hasComment) {
            throw new BusinessException(ErrorResult.disloveError());
        }
        //3、调用API，删除数据，返回点赞数量
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setUserId(UserHolder.getUserId());
        Integer count = commentApi.delete(comment);
        //4、拼接redis的key，删除点赞状态
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return count;
    }




}
